package com.meiling.app;

import android.view.View;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

/**
 * 2022-03-29 13:57
 *
 * @author marisareimu
 */
public class RecyclerScrollImpl extends OnScrollListener {
    private final RecyclerScrollBottomCheckImpl mCallback;
    private int mScrollState = RecyclerView.SCROLL_STATE_IDLE;// SCROLL_STATE_DRAGGING --  View正在被拖动；SCROLL_STATE_SETTLING -- View 正在执行动画到最终的位置（滑动）
    private boolean isArrivedBottom = false;

    public RecyclerScrollImpl(RecyclerScrollBottomCheckImpl mCallback) {
        this.mCallback = mCallback;
    }

    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (mCallback != null) mCallback.onScrollStateChanged(recyclerView, newState);
        mScrollState = newState;
        tripArrived(recyclerView);
    }

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        final int itemCount = recyclerView.getAdapter() != null ? recyclerView.getAdapter().getItemCount() : 0;
        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

        if (layoutManager instanceof LinearLayoutManager) {// 线性布局 -- 对于线性布局管理器，可以
            int firstItem = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
            int lastItem = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            View lastChild = recyclerView.getChildAt(lastItem - firstItem);
            // 保证是最后一个，最后一个Item不为空，且最后一个View完全显示了
            isArrivedBottom = (lastItem == itemCount - 1) && lastChild != null && lastChild.getBottom() <= recyclerView.getMeasuredHeight();
            tripArrived(recyclerView);
        } else if (layoutManager instanceof GridLayoutManager) {// todo 待验证正确性，但基本不会有什么问题，GridLayout并不会想Staggered那样将间隔对其
            int firstItem = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition();
            int lastItem = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
            View lastChild = recyclerView.getChildAt(lastItem - firstItem);
            isArrivedBottom = (lastItem == itemCount - 1) && lastChild != null && lastChild.getBottom() <= recyclerView.getMeasuredHeight();
            tripArrived(recyclerView);
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int[] firstVisibleItems = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(null);
            // 真实Position就是position - firstVisibleItems[0]
            int spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
            int[] lastPositions = new int[spanCount];
            lastPositions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(lastPositions);
            int lastPosition = findMax(lastPositions);
            View lastChild = recyclerView.getChildAt(lastPosition - firstVisibleItems[0]);
            if ((lastPosition == itemCount - 1) && lastChild != null && lastChild.getBottom() <= recyclerView.getMeasuredHeight()) {
                isArrivedBottom = true;
                tripArrived(recyclerView);
            }
//            Ulog.e("lastPositions:" + Gsons.getInstance().toJson(lastPositions)
//                    + "\nfirstVisibleItems:" + Gsons.getInstance().toJson(firstVisibleItems)
//                    + "\nlastPosition:" + lastPosition
//                    + "\nitemCount:" + itemCount
//                    + "\nrecyclerView.getMeasuredHeight():" + recyclerView.getMeasuredHeight()
//                    + (lastChild != null ? ("\nastChild.getBottom():" + lastChild.getBottom()) : ""));
        }
    }

    private int findMax(int[] lastPositions) {
        if (lastPositions != null && lastPositions.length > 0) {
            int temp = 0;
            for (int i = 0; i < lastPositions.length; i++) {
                if (i == 0) temp = lastPositions[i];
                if (temp < lastPositions[i]) {
                    temp = lastPositions[i];
                }
            }
            return temp;
        }
        return 0;
    }

    private void tripArrived(@NonNull RecyclerView recyclerView) {
        if (isArrivedBottom && mScrollState == RecyclerView.SCROLL_STATE_IDLE)
            recyclerView.post(() -> {
                if (mCallback != null) mCallback.arrivedRecyclerViewBottom();
            });
    }

    public interface RecyclerScrollBottomCheckImpl {
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState);

        public void arrivedRecyclerViewBottom();
    }
}
